package com.zygh.lz.service.impl;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zygh.lz.dao.PostDeployMapper;
import com.zygh.lz.entity.dto.PostDeployDTO;
import com.zygh.lz.entity.query.PostDeployCoordinateQuery;
import com.zygh.lz.entity.query.PostDeployQuery;
import com.zygh.lz.entity.vo.*;
import com.zygh.lz.service.PostDeployService;
import com.zygh.lz.service.SignService;
import com.zygh.lz.service.XareaService;
import com.zygh.lz.util.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author jhoal
 */
@Slf4j
@Service
public class PostDeployServiceImpl implements PostDeployService {

    @Resource
    private XareaService xareaService;

    @Resource
    private PostDeployMapper postDeployMapper;

    @Resource
    private SignService signService;

    private static final HashMap<String, String> COLUMN_MAP = new HashMap<String, String>();
    private static final HashMap<String, String> TABLE_JOIN_MAP = new HashMap<String, String>();

    private static final HashMap<String, String> SPECIAL_XCOLUMN_MAP = new HashMap<String, String>();
    private static final HashMap<String, String> SPECIAL_TABLE_JOIN_MAP = new HashMap<String, String>();

    static {
        // 岗位查询相关
        TABLE_JOIN_MAP.put("post", "xarea left join duty_mode on xarea.pattern = duty_mode.code left join sign on xarea.id = sign.assignmentid ");
        COLUMN_MAP.put("post", "xarea.id as xareaId,xarea.name as xareaName,station,xarea.type as xareaType,gps,  battalion, " +
                "detachment, gridding, `rank`, conment, centre,section_Zid,section_Did,startTime,endTime,rwid,whether, " +
                "duty_mode.name as pattern, police, auxiliary, post_code, area_limit, post, '已签到' as postStatus");
        // 未签到
        TABLE_JOIN_MAP.put("postNotChecked", "xarea left join duty_mode on xarea.pattern = duty_mode.code");
        COLUMN_MAP.put("postNotChecked", "xarea.id as xareaId,xarea.name as xareaName,station,xarea.type as xareaType,gps,  battalion, " +
                "detachment, gridding, `rank`, conment, centre,section_Zid,section_Did,startTime,endTime,rwid,whether, " +
                "duty_mode.name as pattern, police, auxiliary, post_code, area_limit, post, '未签到' as postStatus");
        // 警员连接查询相关
        TABLE_JOIN_MAP.put("policeJoin",
                "left join staff on staff.staff_num = sign.warningsignal " +
                        "left join section on staff.sys_section_id = section.sys_section_id ");
        COLUMN_MAP.put("police", "staff.sys_staff_id,IF(staff.stafftype = '民警', '1', '2') as parentId, staff.staff_name, staff.staff_post, staff.sys_section_id, " +
                "staff.staff_num, section.section_name, staff.stafftype, staff.user_status");
        // 警员查询相关
        TABLE_JOIN_MAP.put("police", "sign " +
                "left join staff on staff.staff_num = sign.warningsignal " +
                "left join section on staff.sys_section_id = section.sys_section_id ");
        // 装备连接查询相关
        TABLE_JOIN_MAP.put("equipageJoin", "left join sign_equipage se on sign.signnum = se.signnum left join equipage e on se.gpsid = e.gpsid AND TIMESTAMPDIFF(MINUTE,upload_time,NOW()) <= 60 " +
                " left join equipage_type et on e.type = et.type ");
        COLUMN_MAP.put("equipage", "e.gpsid, et.type_name,et.type_code, e.car_no,e.remark2,e.dept_name");

        TABLE_JOIN_MAP.put("equipage", "sign_equipage se " +
                "         left join equipage e on se.gpsid = e.gpsid AND TIMESTAMPDIFF(MINUTE,upload_time,NOW()) <= 60" +
                "         left join sign on se.signnum = sign.signnum " +
                "         left join staff on staff.staff_num = sign.warningsignal " +
                "         left join equipage_type et on e.type = et.type");

        // 特勤岗位查询相关
        SPECIAL_TABLE_JOIN_MAP.put("post", "xlevelservice left join sptype on position_id = sptype.id left join sign on xlevelservice.id = sign.assignmentid ");
        SPECIAL_XCOLUMN_MAP.put("post", "xlevelservice.id                                                                       as xareaId," +
                "       xlevelservice.place                                                                    as xareaName," +
                "       sptype.ssname                                                                          as station," +
                "       '点'                                                                                   as xareaType," +
                "       xlevelservice.location                                                                 as gps," +
                "       (select section_name from section where sys_section_id = xlevelservice.section_id) as battalion, " +
                "       (select section_name from section where sys_section_id = xlevelservice.section_id) as detachment, " +
                "       xlevelservice.callsign                                                                 as gridding," +
                "       xlevelservice.section_id                                                               as section_Zid," +
                "       xlevelservice.section_id                                                               as section_Did," +
                "       rwid," +
                "       '特勤'                                                                                 as pattern," +
                "       number                                                                                 as police," +
                "       0                                                                                      as auxiliary," +
                "       position_id                                                                            as post_code," +
                "       '已签到'                                                                               as postStatus");
        // 未签到
        SPECIAL_TABLE_JOIN_MAP.put("postNotChecked", "xlevelservice left join sptype on position_id = sptype.id");
        SPECIAL_XCOLUMN_MAP.put("postNotChecked", " xlevelservice.id     as xareaId," +
                "       xlevelservice.place                                                                as xareaName," +
                "       sptype.ssname                                                                      as station," +
                "       '点'                                                                               as xareaType," +
                "       xlevelservice.location                                                             as gps," +
                "       (select section_name from section where sys_section_id = xlevelservice.section_id) as battalion," +
                "       (select section_name from section where sys_section_id = xlevelservice.section_id) as detachment," +
                "       xlevelservice.callsign                                                             as gridding," +
                "       xlevelservice.section_id                                                           as section_Zid," +
                "       xlevelservice.section_id                                                           as section_Did," +
                "       rwid," +
                "       '特勤'                                                                             as pattern," +
                "       number                                                                             as police," +
                "       0                                                                                  as auxiliary," +
                "       position_id                                                                        as post_code," +
                "       '未签到'                                                                           as postStatus");
        // 警员连接查询相关
        SPECIAL_TABLE_JOIN_MAP.put("policeJoin",
                "left join staff on staff.staff_num = sign.warningsignal " +
                        "left join section on staff.sys_section_id = section.sys_section_id ");
        SPECIAL_XCOLUMN_MAP.put("police", "staff.sys_staff_id,IF(staff.stafftype = '民警', '1', '2') as parentId, staff.staff_name, staff.staff_post, staff.sys_section_id, " +
                "staff.staff_num, section.section_name, staff.stafftype, staff.user_status");
        // 警员查询相关
        SPECIAL_TABLE_JOIN_MAP.put("police", "sign " +
                "left join staff on staff.staff_num = sign.warningsignal " +
                "left join section on staff.sys_section_id = section.sys_section_id ");
        // 装备连接查询相关
        SPECIAL_TABLE_JOIN_MAP.put("equipageJoin", "left join sign_equipage se on sign.signnum = se.signnum left join equipage e on se.gpsid = e.gpsid AND TIMESTAMPDIFF(MINUTE,upload_time,NOW()) <= 60 " +
                " left join equipage_type et on e.type = et.type ");
        SPECIAL_XCOLUMN_MAP.put("equipage", "e.gpsid, et.type_name,et.type_code, e.car_no,e.remark2,e.dept_name");

        SPECIAL_TABLE_JOIN_MAP.put("equipage", "sign_equipage se " +
                "         left join equipage e on se.gpsid = e.gpsid AND TIMESTAMPDIFF(MINUTE,upload_time,NOW()) <= 60" +
                "         left join sign on se.signnum = sign.signnum " +
                "         left join staff on staff.staff_num = sign.warningsignal " +
                "         left join equipage_type et on e.type = et.type");
    }

    @Override
    public PostDeployVO getPostDeploy(PostDeployQuery postDeployQuery) {
        // 岗位状态 全部-1、已签到：1、未签到：0
        List<Integer> postStatus = postDeployQuery.getPostStatus();
        // 组装查询条件
        PostDeployDTO postDeployDTO = new PostDeployDTO().build();
        List<Integer> status = new ArrayList<>();
        if (postStatus.contains(-1)) {
            status.add(1);
            status.add(2);
        } else if (postStatus.size() == 0) {
            status.add(1);
        } else {
            status.addAll(postStatus);
        }
        if (postDeployQuery.getSectionIds() != null && postDeployQuery.getSectionIds().contains(74)) {
            postDeployQuery.setSectionIds(null);
        }
        for (Integer integer : status) {
            List<String> arrayList = new ArrayList<>();
            QueryWrapper<PostDeployDTO> wrapper = new QueryWrapper<>();
            Map<String, String> buildSql = new HashMap<>();
            postDeployQuery.setPostStatus(new ArrayList<Integer>() {{
                add(integer);
            }});
            this.buildWrapper(wrapper, arrayList, postDeployQuery, 1);
            // 组装查询字段
            buildSql = this.buildSql(arrayList, integer, COLUMN_MAP, TABLE_JOIN_MAP);
            wrapper.select(buildSql.get("sqlSelect"));
            String tableName = buildSql.get("tableName");

            log.debug("tableName = {}", tableName);
            log.debug("sqlSelect = {}", wrapper.getSqlSelect());
            log.debug("getCustomSqlSegment = {}", wrapper.getCustomSqlSegment());
            // 查询数据
            PostDeployDTO deployDTO = postDeployMapper.queryPostDeploy(wrapper, tableName);
            if (deployDTO == null) {
                continue;
            }
            postDeployDTO.getPost().addAll(deployDTO.getPost());
            postDeployDTO.getEquipage().addAll(deployDTO.getEquipage());
            postDeployDTO.getPolice().addAll(deployDTO.getPolice());
        }
        PostDeployVO postDeployVO = new PostDeployVO();
        // 将数据按组分类后装入返回结果
        Map<String, List<XareaVO>> station = groupBy(postDeployDTO.getPost(), "station");
        station.forEach((k, v) -> {
            PostDeployVO.ValueInfo<XareaVO> valueInfo = new PostDeployVO.ValueInfo<>();
            valueInfo.setName(k);
            valueInfo.setId(String.valueOf(v.get(0).getPostCode()));
            valueInfo.setValue(v);
            postDeployVO.getPost().add(valueInfo);
        });
        Map<String, List<StaffVO>> stafftype = groupBy(postDeployDTO.getPolice(), "stafftype");
        stafftype.forEach((k, v) -> {
            PostDeployVO.ValueInfo<StaffVO> valueInfo = new PostDeployVO.ValueInfo<>();
            valueInfo.setName(k);
            valueInfo.setId("民警".equals(k) ? "1" : "2");
            valueInfo.setValue(v);
            postDeployVO.getPolice().add(valueInfo);
        });
        Map<String, List<EquipageVO>> type = groupBy(postDeployDTO.getEquipage(), "type");
        type.forEach((k, v) -> {
            PostDeployVO.ValueInfo<EquipageVO> valueInfo = new PostDeployVO.ValueInfo<>();
            valueInfo.setName(k);
            valueInfo.setId(String.valueOf(v.get(0).getTypeCode()));
            valueInfo.setValue(v);
            postDeployVO.getEquipage().add(valueInfo);
        });
        return postDeployVO;
    }

    @Override
    public PostDeployVO getSpecialPostDeploy(PostDeployQuery postDeployQuery) {
        // 岗位状态 全部-1、已签到：1、未签到：0
        List<Integer> postStatus = postDeployQuery.getPostStatus();
        // 组装查询条件
        PostDeployDTO postDeployDTO = new PostDeployDTO().build();
        List<Integer> status = new ArrayList<>();
        if (postStatus.contains(-1)) {
            status.add(1);
            status.add(2);
        } else if (postStatus.size() == 0) {
            status.add(1);
        } else {
            status.addAll(postStatus);
        }
        if (postDeployQuery.getSectionIds() != null && postDeployQuery.getSectionIds().contains(74)) {
            postDeployQuery.setSectionIds(null);
        }
        for (Integer integer : status) {
            List<String> arrayList = new ArrayList<>();
            QueryWrapper<PostDeployDTO> wrapper = new QueryWrapper<>();
            Map<String, String> buildSql = new HashMap<>();
            postDeployQuery.setPostStatus(new ArrayList<Integer>() {{
                add(integer);
            }});
            this.buildWrapper(wrapper, arrayList, postDeployQuery, 2);
            // 组装查询字段
            buildSql = this.buildSql(arrayList, integer, SPECIAL_XCOLUMN_MAP, SPECIAL_TABLE_JOIN_MAP);
            wrapper.select(buildSql.get("sqlSelect"));
            String tableName = buildSql.get("tableName");

            log.debug("tableName = {}", tableName);
            log.debug("sqlSelect = {}", wrapper.getSqlSelect());
            log.debug("getCustomSqlSegment = {}", wrapper.getCustomSqlSegment());
            // 查询数据
            PostDeployDTO deployDTO = postDeployMapper.queryPostDeploy(wrapper, tableName);
            if (deployDTO == null) {
                continue;
            }
            postDeployDTO.getPost().addAll(deployDTO.getPost());
            postDeployDTO.getEquipage().addAll(deployDTO.getEquipage());
            postDeployDTO.getPolice().addAll(deployDTO.getPolice());
        }
        PostDeployVO postDeployVO = new PostDeployVO();
        // 将数据按组分类后装入返回结果
        Map<String, List<XareaVO>> station = groupBy(postDeployDTO.getPost(), "station");
        station.forEach((k, v) -> {
            PostDeployVO.ValueInfo<XareaVO> valueInfo = new PostDeployVO.ValueInfo<>();
            valueInfo.setName(k);
            valueInfo.setId(String.valueOf(v.get(0).getPostCode()));
            valueInfo.setValue(v);
            postDeployVO.getPost().add(valueInfo);
        });
        Map<String, List<StaffVO>> stafftype = groupBy(postDeployDTO.getPolice(), "stafftype");
        stafftype.forEach((k, v) -> {
            PostDeployVO.ValueInfo<StaffVO> valueInfo = new PostDeployVO.ValueInfo<>();
            valueInfo.setName(k);
            valueInfo.setId("民警".equals(k) ? "1" : "2");
            valueInfo.setValue(v);
            postDeployVO.getPolice().add(valueInfo);
        });
        Map<String, List<EquipageVO>> type = groupBy(postDeployDTO.getEquipage(), "type");
        type.forEach((k, v) -> {
            PostDeployVO.ValueInfo<EquipageVO> valueInfo = new PostDeployVO.ValueInfo<>();
            valueInfo.setName(k);
            valueInfo.setId(String.valueOf(v.get(0).getTypeCode()));
            valueInfo.setValue(v);
            postDeployVO.getEquipage().add(valueInfo);
        });
        return postDeployVO;
    }

    <T> Map<String, List<T>> groupBy(List<T> list, String key) {
        Map<String, List<T>> map = new HashMap<>();
        for (T object : list) {
            JSONObject map1 = JSONUtil.parseObj(object);
            String groupFlag = map1.getStr(key);
            if (groupFlag == null) {
                continue;
            }
            if (map.get(groupFlag) != null) {
                map.get(groupFlag).add(object);
            } else {
                List<T> list1 = new ArrayList<>();
                list1.add(object);
                map.put(groupFlag, list1);
            }
        }
        return map;
    }

    void buildWrapper(QueryWrapper<PostDeployDTO> lambda, List<String> arrayList, PostDeployQuery postDeployQuery, Integer type) {
        // 岗位编号
        List<Integer> postCode = postDeployQuery.getPostCode();
        // 部门id
        List<Integer> sectionIds = postDeployQuery.getSectionIds();
// 岗位状态 全部-1、已签到：1、未签到：0
        List<Integer> postStatus = postDeployQuery.getPostStatus();
        //警员类别 全部-1、民警：1、辅警：0
        List<Integer> policeCategory = postDeployQuery.getPoliceCategory();
        // 设备类型
        List<Integer> equipmentTypeCode = postDeployQuery.getEquipmentTypeId();

        if (postStatus != null && postStatus.size() > 0) {
            if (postStatus.contains(2) && postStatus.size() == 1) {
                // 筛选岗位编号
                if (postCode != null && postCode.size() > 0) {
                    arrayList.add("post");
                    if (!postCode.contains(-1)) {
                        if (type == 1) {
                            lambda.in("post_code", postCode);
                        } else {
                            lambda.in("position_id", postCode);
                        }
                    }
                    List<Integer> postId = signService.getTodaySignInPostId(type);
                    if (type == 1) {
                        lambda.notIn(postId.size() > 0, "xarea.id", postId);
                    } else {
                        lambda.notIn(postId.size() > 0, "xlevelservice.id", postId);
                    }
                } else {
                    arrayList.add("post");
                }
                return;
            } else {
                lambda.between("signintime", DateUtils.getDayBegin(), DateUtils.getDayEnd());
            }
        }

        // 筛选岗位编号
        if (postCode != null && postCode.size() > 0) {
            arrayList.add("post");
            if (!postCode.contains(-1)) {
                if (type == 1) {
                    lambda.in("post_code", postCode);
                } else {
                    lambda.in("position_id", postCode);
                }
            }
        }

        if (policeCategory != null && policeCategory.size() > 0) {
            arrayList.add("police");
            // 岗位状态已签到
            lambda.between("signintime", DateUtils.getDayBegin(), DateUtils.getDayEnd());
            if (!policeCategory.contains(-1)) {
                lambda.eq("staff.stafftype", policeCategory.contains(1) ? "民警" : "辅警");
            }
        }

        if (equipmentTypeCode != null && equipmentTypeCode.size() > 0) {
            arrayList.add("equipage");
            if (!arrayList.contains("police")) {
                lambda.between("signintime", DateUtils.getDayBegin(), DateUtils.getDayEnd());
            }
//            lambda.between("se.create_time", DateUtils.getDayBegin(), DateUtils.getDayEnd());
            if (!equipmentTypeCode.contains(-1)) {
                lambda.in("et.type_code", equipmentTypeCode);
            }
        }

        // 筛选 单位编号
        if (sectionIds != null && sectionIds.size() > 0) {
            if (arrayList.contains("post")) {
                if (type == 1) {
                    lambda.and(temp -> temp.in("section_Did", sectionIds).or().in("section_Zid", sectionIds));
                } else {
                    lambda.in("section_id", sectionIds);
                }
            } else {
                lambda.in("staff.sys_section_id", sectionIds);
            }
        }

    }

    Map<String, String> buildSql(List<String> list, Integer postStatus, Map<String, String> column_map, Map<String, String> table_join_map) {
        StringBuffer tableName = new StringBuffer();
        StringBuffer column = new StringBuffer();
        for (int i = 0; i < list.size(); i++) {
            if (postStatus == 2) {
                tableName.append(table_join_map.get("postNotChecked"));
                column.append(column_map.get("postNotChecked"));
                break;
            }
            if ("police".equals(list.get(i)) && list.contains("post")) {
                tableName.append(table_join_map.get(list.get(i) + "Join"));
            } else if ("equipage".equals(list.get(i)) && (list.contains("police") || list.contains("post"))) {
                tableName.append(table_join_map.get(list.get(i) + "Join"));
            } else {
                tableName.append(table_join_map.get(list.get(i)));
            }
            column.append(column_map.get(list.get(i)));
            if (i != list.size() - 1) {
                column.append(",");
            }
        }
        HashMap<String, String> hashMap = new HashMap<>();
        hashMap.put("tableName", tableName.toString());
        hashMap.put("sqlSelect", column.toString());
        return hashMap;
    }


    @Override
    public XareaVO getPostDeployById(Long id) {
        XareaVO xareaVO = postDeployMapper.getPostDeployById(id);
        AtomicInteger policeNumber = new AtomicInteger();
        AtomicInteger auxiliaryPoliceNumber = new AtomicInteger();
        xareaVO.getStaffList().forEach(staffVO -> {
            if ("民警".equals(staffVO.getStafftype())) {
                policeNumber.getAndIncrement();
            }
            if ("辅警".equals(staffVO.getStafftype())) {
                auxiliaryPoliceNumber.getAndIncrement();
            }
        });
        xareaVO.setSumPolice(policeNumber.get());
        xareaVO.setSumAuxiliary(auxiliaryPoliceNumber.get());
        return xareaVO;
    }

    @Override
    public EquipageDetailVO getEquipageDetailById(String gpsid) {
        return postDeployMapper.getEquipageDetailById(gpsid);
    }

    @Override
    public PostDeployDTO getCoordinate(PostDeployCoordinateQuery postDeployCoordinateQuery) {
        PostDeployDTO deployDTO = new PostDeployDTO().build();
        if (postDeployCoordinateQuery.getPostIds() != null && postDeployCoordinateQuery.getPostIds().size() > 0) {
            List<XareaVO> xareaVOS = postDeployMapper.getPostListByIdList(postDeployCoordinateQuery.getPostIds());
            deployDTO.setPost(xareaVOS);
        }
        if (postDeployCoordinateQuery.getPoliceNumber() != null && postDeployCoordinateQuery.getPoliceNumber().size() > 0) {
            List<StaffVO> staffVOS = postDeployMapper.getPoliceByNumberList(postDeployCoordinateQuery.getPoliceNumber());
            deployDTO.setPolice(staffVOS);
        }
        if (postDeployCoordinateQuery.getEquipageGpsIdList() != null && postDeployCoordinateQuery.getEquipageGpsIdList().size() > 0) {
            List<EquipageVO> equipage = postDeployMapper.getEquipageByGpsIdList(postDeployCoordinateQuery.getEquipageGpsIdList());
            deployDTO.setEquipage(equipage);
        }

        return deployDTO;
    }

    @Override
    public XareaVO getSpecialPostDeployById(Long id) {
        XareaVO xareaVO = postDeployMapper.getSpecialPostDeployById(id);
        AtomicInteger policeNumber = new AtomicInteger();
        AtomicInteger auxiliaryPoliceNumber = new AtomicInteger();
        xareaVO.getStaffList().forEach(staffVO -> {
            if ("民警".equals(staffVO.getStafftype())) {
                policeNumber.getAndIncrement();
            }
            if ("辅警".equals(staffVO.getStafftype())) {
                auxiliaryPoliceNumber.getAndIncrement();
            }
        });
        xareaVO.setSumPolice(policeNumber.get());
        xareaVO.setSumAuxiliary(auxiliaryPoliceNumber.get());
        return xareaVO;
    }

    @Override
    public PostDeployDTO getSpecialPostDeployCoordinate(PostDeployCoordinateQuery postDeployCoordinateQuery) {
        PostDeployDTO deployDTO = new PostDeployDTO().build();
        if (postDeployCoordinateQuery.getPostIds() != null && postDeployCoordinateQuery.getPostIds().size() > 0) {
            List<XareaVO> xareaVOS = postDeployMapper.getSpecialPostListByIdList(postDeployCoordinateQuery.getPostIds());
            deployDTO.setPost(xareaVOS);
        }
        if (postDeployCoordinateQuery.getPoliceNumber() != null && postDeployCoordinateQuery.getPoliceNumber().size() > 0) {
            List<StaffVO> staffVOS = postDeployMapper.getPoliceByNumberList(postDeployCoordinateQuery.getPoliceNumber());
            deployDTO.setPolice(staffVOS);
        }
        if (postDeployCoordinateQuery.getEquipageGpsIdList() != null && postDeployCoordinateQuery.getEquipageGpsIdList().size() > 0) {
            List<EquipageVO> equipage = postDeployMapper.getEquipageByGpsIdList(postDeployCoordinateQuery.getEquipageGpsIdList());
            deployDTO.setEquipage(equipage);
        }

        return deployDTO;
    }

    @Override
    public List<EquipageDetailVO> getEquipageDetailByIds(List<String> gpsIds) {
        return postDeployMapper.getEquipageDetailByIds(gpsIds);
    }
}
